/*******************************************************
**     usart send and receive driver
** Example:
**         << usart receive data >>
** Method 1>>
** 		awesomeUsartLowSaveReadBuff(&awesomeUsart, data); //low hardware usart save data 
**		len = awesomeUsartCanRead(&awesomeUsart);
**      for(i=0; i<len; ++i){
**			awesomeUsartRead(&awesomeUsart, &data);
**			//do some work 
**		}
** Method 2>>
** 		awesomeUsartLowSaveReadBuff(&awesomeUsart, data); //low hardware usart save data 
**		len = awesomeUsartReads(&awesomeUsart, &buff[0], getlen);
**      for(i=0; i<len; ++i){
**			//do some work buff[i]
**		}
**
**
**         << usart send data >>
** 		awesomeUsartWrite() or awesomeUsartWrites();
**      awesomeUsartLowGetWriteBuff(&awesomeUsart, &buff, len); //low hardware send data from buff[] 
**
********************************************************/


#ifndef AWESOME_USART_H
#define AWESOME_USART_H

#define AWESOME_USART_DEBUG 1

__inline void set_PRIMASK(unsigned int priMask)
{
  register unsigned int __regPriMask         __asm("primask");
  __regPriMask = (priMask);
}


#define CLOSE_IRP()  set_PRIMASK(1)
#define OPEN_IRP()   set_PRIMASK(0)

typedef struct _awesome_usart{
	#if (AWESOME_USART_DEBUG==1)
		unsigned char rx_error;
	  unsigned char tx_error;
	#endif
	unsigned char* prxdata;					//rx data buff
	unsigned char* ptxdata;					//tx data buff
	volatile unsigned int rxDataCount;      //rx data count 
	volatile unsigned int rxReadDataPos;    //rx read buff data position
	volatile unsigned int rxWriteDataPos;   //rx write to rx buff data
	volatile unsigned int txDataCount;      //tx data count
	volatile unsigned int txReadDataPos;    //read tx buff data position
	volatile unsigned int txWriteDataPos;   //write tx buff data position
	volatile unsigned int rxCapacity;       //rx data buff capacity
	volatile unsigned int txCapacity;       //tx data buff capacity
	unsigned int (*can_read)(struct _awesome_usart* puart);
	unsigned int (*can_write)(struct _awesome_usart* puart);
	unsigned char  (*write)(struct _awesome_usart* puart, unsigned char data);
	unsigned int (*writes)(struct _awesome_usart* puart, unsigned char *data, unsigned int len);
	unsigned char (*read)(struct _awesome_usart* puart);
	unsigned int (*reads)(struct _awesome_usart* puart, unsigned char* data, unsigned int len);
	
	char (*low_set_read_buff)(struct _awesome_usart* puart, unsigned char* data, unsigned int len);
	unsigned int (*low_get_write_buff)(struct _awesome_usart* puart, unsigned char* data, unsigned int len);
}awesome_usart;

/* software init */ 
unsigned char awesome_usart_init(awesome_usart* puart, unsigned char* prx, unsigned int rxcap, unsigned char* ptx, unsigned int txcap);

/* usart rx data buff is full: return can send data count */ 
static unsigned int can_read(awesome_usart* puart);

/* usart tx data buff is full: return can rx data count */ 
static unsigned int can_write(awesome_usart* puart);

/* data write send data buff, return write data len */ 
static unsigned char write(awesome_usart* puart, unsigned char data);

/* data write send data buff: success=1, other=-1 */ 
static unsigned int writes(awesome_usart* puart, unsigned char *data, unsigned int len);

/* usart read data from data buff, read success=data len, other 0*/
static unsigned int reads(awesome_usart* puart, unsigned char* data, unsigned int len);

/* read a data, need call awesomeUsartCanRead() before get data len: success=1, other=-1*/ 
static unsigned char read(awesome_usart* puart);

/* Low callback: hardware usart rx data to save buff */ 
static char low_set_read_buff(awesome_usart* puart, unsigned char* data, unsigned int len);

static unsigned int low_get_write_buff(awesome_usart* puart, unsigned char* data, unsigned int len);

#endif
